package com.vf.admin.client.controller.wechatlogin.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * 通用http发送方法
 *
 * @author ruoyi
 */
public class HttpUtils
{
    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);

    private static HttpClientBuilder clientBuilder = HttpClientBuilder.create();

    static {
//        System.setProperty("https.protocols", "TLSv1");
        clientBuilder.useSystemProperties();
    }

    private static CloseableHttpClient createHttpClient() {
        return clientBuilder.build();
    }

    /**
     * Execute http get.
     *
     * @param url      the url
     * @param paramMap the param map
     * @return the string
     */
    public static String executeHttpGet(String url, Map<String, Object> paramMap) throws IOException {
        CloseableHttpClient httpClient = createHttpClient();
        StringBuffer buf = new StringBuffer(url);

        if (!url.contains("?")) {
            buf.append("?");
        }

        if (paramMap != null) {
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                buf.append("&").append(entry.getKey()).append("=").append(encodeUrl(entry.getValue() + ""));
            }
        }

        HttpGet httpGet = new HttpGet(buf.toString());

        try {
            HttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            String content = EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
            return content;
        } finally {
            httpGet.releaseConnection();
            httpClient.close();
        }
    }


    /**
     * Execute http post.
     *
     * @param url      the url
     * @param paramMap the param map
     * @return the string
     */
    public static String executeHttpPost(String url, Map<String, Object> paramMap) throws IOException {
        CloseableHttpClient httpclient = createHttpClient();
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> nvps = new ArrayList<>();

        for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
            Object val = paramMap.get(entry.getKey());
            String value = val == null ? null : val.toString();
            nvps.add(new BasicNameValuePair(entry.getKey(), value));
        }

        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
            HttpResponse response = httpclient.execute(httpPost);

            HttpEntity entity = response.getEntity();
            String content = EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
            return content;
        } finally {
            httpPost.releaseConnection();
            httpclient.close();
        }
    }
    public static String executeHttpPostXml(String url, String body) throws IOException {
        CloseableHttpClient httpclient = createHttpClient();
        HttpPost httpPost = new HttpPost(url);
        try {
            StringEntity entity1 = new StringEntity(body, "GBK");
            entity1.setContentType("text/xml;charset=GBK");
            httpPost.setEntity(entity1);
            HttpResponse response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String content = EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
            return content;
        } finally {
            httpPost.releaseConnection();
            httpclient.close();
        }
    }
    /**
     * Execute http post.
     *
     * @param url      the url
     * @param paramMap the param map
     * @return the string
     */
    public static String executeHttpPostXML(String url, Map<String, Object> paramMap) throws IOException {
        CloseableHttpClient httpclient = createHttpClient();
        HttpPost httpPost = new HttpPost(url);
        StringBuilder xml = new StringBuilder("<xml>");

        for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            Object value = String.valueOf(entry.getValue());
            xml.append("<").append(key).append(">").append(value).append("</").append(key).append(">");
        }
        xml.append("</xml>");

        try {
            httpPost.setHeader("Content-type", "text/xml; charset=utf-8");
            // List<NameValuePair> params = new ArrayList<NameValuePair>();
            // params.add(new BasicNameValuePair("$xmldata", xml.toString()));
            // httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));

            StringEntity entity1 = new StringEntity(xml.toString(), "UTF-8");
            entity1.setContentType("text/xml;charset=UTF-8");
            entity1.setContentEncoding("UTF-8");
            httpPost.setEntity(entity1);

            HttpResponse response = httpclient.execute(httpPost);

            HttpEntity entity = response.getEntity();
            String content = EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
            return content;
        } finally {
            httpPost.releaseConnection();
            httpclient.close();
        }
    }

    public static String executeHttpPostJson(String url, Map<String, Object> paramMap) throws IOException {
        CloseableHttpClient httpclient = createHttpClient();
        HttpPost httpPost = new HttpPost(url);

        try {
            String jsonString = JSONObject.toJSONString(paramMap);
            StringEntity entity1 = new StringEntity(jsonString, "UTF-8");
            entity1.setContentType("application/json;charset=UTF-8");
            httpPost.setEntity(entity1);
            HttpResponse response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String content = EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
            return content;
        } finally {
            httpPost.releaseConnection();
            httpclient.close();
        }
    }

    public static String executeHttpPostJson(String url, String  jsonString) throws IOException {
        CloseableHttpClient httpclient = createHttpClient();
        HttpPost httpPost = new HttpPost(url);

        try {
            StringEntity entity1 = new StringEntity(jsonString, "UTF-8");
            entity1.setContentType("application/json;charset=UTF-8");
            httpPost.setEntity(entity1);
            HttpResponse response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String content = EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
            return content;
        } finally {
            httpPost.releaseConnection();
            httpclient.close();
        }
    }



//    public static RespResult executePost(String url, Map<String, Object> paramMap) throws IOException {
//        CloseableHttpClient httpclient = createHttpClient();
//        HttpPost httpPost = new HttpPost(url);
//
//        try {
//            String jsonString = JSONObject.toJSONString(paramMap);
//            // System.out.println("result_code=SUCCESS");
//            // httpPost.setHeader("Content-type",
//            // "application/json; charset=utf-8");
//            StringEntity entity1 = new StringEntity(jsonString, "UTF-8");
//            entity1.setContentType("application/json;charset=UTF-8");
//            httpPost.setEntity(entity1);
//            HttpResponse response = httpclient.execute(httpPost);
//            HttpEntity entity = response.getEntity();
//            RespResult respResult = new RespResult();
//            respResult.setErrcode(0);
//            if(entity.getContentType().getValue().contains("application/json; charset=UTF-8")) {
//            	 String content = EntityUtils.toString(entity, "utf-8");
//                 EntityUtils.consume(entity);
//            	 respResult.setJsonObject(JSONObject.parseObject(content));
//            } else {
//            	respResult.setContent(EntityUtils.toByteArray(entity));
//            	EntityUtils.consume(entity);
//            }
//
//            return respResult;
//        } finally {
//            httpPost.releaseConnection();
//            httpclient.close();
//        }
//    }

    /**
     * Encode url.
     *
     * @param param the param
     * @return the string
     */
    public static String encodeUrl(String param) {
        try {
            return URLEncoder.encode(param, "utf-8");
        } catch (Exception e) {
            return param;
        }
    }

    /**
     * Execute http 获取json 数据
     *
     * @param url      the url
     * @return the string
     */
    public static String executeHttpGet(String url) throws IOException {
        CloseableHttpClient httpClient = createHttpClient();

        HttpGet httpGet = new HttpGet(url);

        try {
            HttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            String content = EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
            return content;
        } finally {
            httpGet.releaseConnection();
            httpClient.close();
        }
    }

    /**
     * 向指定 URL 发送GET方法的请求
     *
     * @param url 发送请求的 URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param)
    {
        StringBuilder result = new StringBuilder();
        BufferedReader in = null;
        try
        {
            String urlNameString = url + "?" + param;
            log.info("sendGet - {}", urlNameString);
            URL realUrl = new URL(urlNameString);
            URLConnection connection = realUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.connect();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null)
            {
                result.append(line);
            }
            log.info("recv - {}", result);
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
        }
        finally
        {
            try
            {
                if (in != null)
                {
                    in.close();
                }
            }
            catch (Exception ex)
            {
                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }

    /**
     * 向指定 URL 发送GET方法的请求
     *
     * @param url 发送请求的 URL
     * @return 所代表远程资源的响应结果
     */
    public static byte[] sendGet(String url)
    {
    	byte result[] = null;
        BufferedInputStream in = null;
        ByteArrayOutputStream output = null;
        try
        {
            log.info("sendGet - {}", url);
            URL realUrl = new URL(url);
            URLConnection connection = realUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.connect();
            in = new BufferedInputStream(connection.getInputStream());

            output = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            int numBytesRead = 0;
            while ((numBytesRead = in.read(buf)) != -1) {
                output.write(buf, 0, numBytesRead);
            }
            result = output.toByteArray();



        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendGet ConnectException, url=" + url, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendGet IOException, url=" + url, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendGet Exception, url=" + url, e);
        }
        finally
        {
            try
            {
                if (in != null)
                {
                    in.close();
                }
            }
            catch (Exception ex)
            {
                log.error("调用in.close Exception, url=" + url, ex);
            }
        }
        return result;
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url 发送请求的 URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param)
    {
        PrintWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try
        {
            String urlNameString = url + "?" + param;
            log.info("sendPost - {}", urlNameString);
            URL realUrl = new URL(urlNameString);
            URLConnection conn = realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("contentType", "utf-8");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            out = new PrintWriter(conn.getOutputStream());
            out.print(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
            String line;
            while ((line = in.readLine()) != null)
            {
                result.append(line);
            }
            log.info("recv - {}", result);
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
        }
        finally
        {
            try
            {
                if (out != null)
                {
                    out.close();
                }
                if (in != null)
                {
                    in.close();
                }
            }
            catch (IOException ex)
            {
                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }

    public static String sendSSLPost(String url, String param)
    {
        StringBuilder result = new StringBuilder();
        String urlNameString = url + "?" + param;
        try
        {
            log.info("sendSSLPost - {}", urlNameString);
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
            URL console = new URL(urlNameString);
            HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("contentType", "utf-8");
            conn.setDoOutput(true);
            conn.setDoInput(true);

            conn.setSSLSocketFactory(sc.getSocketFactory());
            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
            conn.connect();
            InputStream is = conn.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String ret = "";
            while ((ret = br.readLine()) != null)
            {
                if (ret != null && !ret.trim().equals(""))
                {
                    result.append(new String(ret.getBytes("ISO-8859-1"), "utf-8"));
                }
            }
            log.info("recv - {}", result);
            conn.disconnect();
            br.close();
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
        }
        return result.toString();
    }

    private static class TrustAnyTrustManager implements X509TrustManager
    {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
        {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)
        {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers()
        {
            return new X509Certificate[] {};
        }
    }

    private static class TrustAnyHostnameVerifier implements HostnameVerifier
    {
        @Override
        public boolean verify(String hostname, SSLSession session)
        {
            return true;
        }
    }
}
